package cn.cai.pethome.emp.interceptor;

import cn.cai.pethome.base.PreAuthorize;
import cn.cai.pethome.base.dto.LogininfoDto;
import cn.cai.pethome.base.util.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.PublicKey;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class AuthenticationInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisTemplate redisTemplate;


    @Autowired
    private UserContext userContext;

    /**
     * 前置拦截
     *  pre：previous的简写，表示前一个的意思
     *  post：后置拦截
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        try {
            //1.先获取请求头 U-TOKEN
            String token = request.getHeader("U-TOKEN");
            if (StringUtils.hasText(token)){
                //2.再以token为key到Redis中获取用户json
              /*  Object loginUserJsonString = redisTemplate.opsForValue().get(token);
                if (loginUserJsonString != null){
                    //重新刷新过期时间，再设置30分钟
                    redisTemplate.opsForValue().set(token,loginUserJsonString,30, TimeUnit.MINUTES);

                    return true;//放行*/

                LogininfoDto logininfoDto = userContext.getUser(token);//调方法

                if (logininfoDto.getLogininfo() != null && logininfoDto != null){
                    //前台用户登录过了直接放行 不需要校验权限
                    if (logininfoDto.getLogininfo().getType() == 1){
                        return true;
                    }
                    //3.检查当前访问的资源是否需要校验权限，如果需要的话，还要校验当前登录用户是否拥有该权限
                    HandlerMethod handlerMethod = (HandlerMethod) handler;
                    //用户本次请求访问的资源方法上面没有PreAuthorize注解，则无需校验权限，只要登录过的就直接放行c
                    if (!handlerMethod.hasMethodAnnotation(PreAuthorize.class)){
                        return true;
                    }
                    //有注解：就获取注解
                    PreAuthorize preAuthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class);
                    //需要校验的权限
                    String sn = preAuthorize.sn();
                    //获取当前登录用户拥有的权限列表
                    List<String> ownPermissions = logininfoDto.getOwnPermissions();
                    if (ownPermissions != null && ownPermissions.contains(sn)){

                        return  true;
                    }else {
                        //检测到用户无权限，响应给前端一个json数据
                        AjaxResult ajaxResult = AjaxResult.error("noPermission");
                        ////////////// 下面这几行代码，就是@ResponseBody注解的底层实现 /////////////
                        //将对象转化为json字符串，使用了jackson工具包
                        String jsonString = new ObjectMapper().writeValueAsString(ajaxResult);
                        response.setContentType("application/json;charset=utf-8");
                        response.getWriter().write(jsonString);
                        return false;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //检测到用户未登录，响应给前端一个json数据
        AjaxResult ajaxResult = AjaxResult.error("noLogin");
        //将对象转化为json字符串，使用了jackson工具包
        String jsonString = new ObjectMapper().writeValueAsString(ajaxResult);
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(jsonString);
        return false;
    }
}
